using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
using Newtonsoft.Json.Linq;

namespace DidaManager.Models.JsonConvert
{
    /// <summary>
    /// MQTT配置转换类，用于读取和解析MQTT配置文件
    /// </summary>
    public class MqttConvertToDownloadFile
    {
        // 默认值常量
        private const int DEFAULT_SERVER_TYPE = 1001;
        private const int DEFAULT_NETWORK_TYPE = 5000;
        private const int DEFAULT_TOPIC_TYPE = 4001;
        private const int DEFAULT_PAYLOAD_TYPE = 2001;

        /// <summary>
        /// 从JSON字符串解析MQTT配置数据并转换为下载格式
        /// </summary>
        /// <param name="filePath">文件路径</param>
        public static void ParseDbJsonAndSave(string filePath,Dictionary<string,int> dict)
        {
            if (!File.Exists(filePath))
            {
                throw new FileNotFoundException($"文件不存在: {filePath}");
            }

            string jsonContent = File.ReadAllText(filePath);
            if (string.IsNullOrEmpty(jsonContent))
            {
                throw new ArgumentException("JSON内容不能为空");
            }

            // 使用 JArray 解析 JSON
            JArray jsonArray = JArray.Parse(jsonContent);
            var devices = new List<DatabaseMqttDevice>();

            foreach (JObject deviceJson in jsonArray)
            {
                var device = MapJsonToObject<DatabaseMqttDevice>(deviceJson);
                devices.Add(device);
            }

            var downloadConfig = ConvertToDownloadFormat(devices,dict);
            SaveDownloadConfigToFile(downloadConfig, filePath);
        }

        /// <summary>
        /// 通用的 JSON 到对象映射方法
        /// </summary>
        /// <typeparam name="T">目标类型</typeparam>
        /// <param name="json">JSON对象</param>
        /// <returns>映射后的对象</returns>
        private static T MapJsonToObject<T>(JObject json) where T : class, new()
        {
            var obj = new T();
            var properties = typeof(T).GetProperties();

            foreach (var prop in properties)
            {
                var jsonPropertyName = GetJsonPropertyName(prop);
                if (json.TryGetValue(jsonPropertyName, out JToken? value) && value != null)
                {
                    SetPropertyValue(obj, prop, value);
                }
            }

            return obj;
        }

        /// <summary>
        /// 获取属性对应的 JSON 字段名
        /// </summary>
        /// <param name="prop">属性信息</param>
        /// <returns>JSON字段名</returns>
        private static string GetJsonPropertyName(PropertyInfo prop)
        {
            var jsonPropertyAttribute = prop.GetCustomAttribute<JsonPropertyNameAttribute>();
            return jsonPropertyAttribute?.Name ?? prop.Name;
        }

        /// <summary>
        /// 设置属性值，支持嵌套对象和集合
        /// </summary>
        /// <param name="obj">目标对象</param>
        /// <param name="prop">属性信息</param>
        /// <param name="value">JSON值</param>
        private static void SetPropertyValue(object obj, PropertyInfo prop, JToken value)
        {
            try
            {
                if (prop.PropertyType == typeof(DatabaseMqttConfig))
                {
                    // 递归处理 Config 对象
                    var config = MapJsonToObject<DatabaseMqttConfig>((JObject)value);
                    prop.SetValue(obj, config);
                }
                else if (prop.PropertyType == typeof(List<DatabaseMqttTopic>))
                {
                    // 处理 Topic 列表
                    if (value is JArray topicArray)
                    {
                        var topics = topicArray.Select(t => MapJsonToObject<DatabaseMqttTopic>((JObject)t)).ToList();
                        prop.SetValue(obj, topics);
                    }
                }
                else
                {
                    // 处理基础类型，自动转换
                    var convertedValue = ConvertValue(value, prop.PropertyType);
                    prop.SetValue(obj, convertedValue);
                }
            }
            catch
            {
                // 转换失败时使用默认值
                var defaultValue = GetDefaultValue(prop.PropertyType);
                prop.SetValue(obj, defaultValue);
            }
        }

        /// <summary>
        /// 转换 JSON 值到指定类型
        /// </summary>
        /// <param name="value">JSON值</param>
        /// <param name="targetType">目标类型</param>
        /// <returns>转换后的值</returns>
        private static object? ConvertValue(JToken value, Type targetType)
        {
            if (value.Type == JTokenType.Null)
                return GetDefaultValue(targetType);

            // 处理可空类型
            if (targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof(Nullable<>))
            {
                targetType = Nullable.GetUnderlyingType(targetType)!;
            }

            // 特殊处理字符串类型
            if (targetType == typeof(string))
            {
                return value.ToString();
            }

            // 特殊处理布尔类型
            if (targetType == typeof(bool))
            {
                if (value.Type == JTokenType.Boolean)
                    return value.Value<bool>();
                if (value.Type == JTokenType.String)
                    return bool.TryParse(value.ToString(), out bool boolResult) && boolResult;
                return false;
            }

            // 特殊处理整数类型
            if (targetType == typeof(int))
            {
                if (value.Type == JTokenType.Integer)
                    return value.Value<int>();
                if (value.Type == JTokenType.String && int.TryParse(value.ToString(), out int intResult))
                    return intResult;
                return 0;
            }

            // 其他类型使用通用转换
            try
            {
                return Convert.ChangeType(value.ToString(), targetType);
            }
            catch
            {
                return GetDefaultValue(targetType);
            }
        }

        /// <summary>
        /// 获取类型的默认值
        /// </summary>
        /// <param name="type">类型</param>
        /// <returns>默认值</returns>
        private static object? GetDefaultValue(Type type)
        {
            if (type.IsValueType)
            {
                return Activator.CreateInstance(type);
            }

            if (type == typeof(string))
            {
                return string.Empty;
            }

            if (type == typeof(List<DatabaseMqttTopic>))
            {
                return new List<DatabaseMqttTopic>();
            }

            if (type == typeof(DatabaseMqttConfig))
            {
                return new DatabaseMqttConfig();
            }

            return null;
        }

        /// <summary>
        /// 将原始MQTT格式转换为新的目标格式
        /// </summary>
        /// <param name="devices">原始MQTT设备列表</param>
        /// <returns>转换后的MQTT配置</returns>
        public static MqttDownloadConfig ConvertToDownloadFormat(List<DatabaseMqttDevice> devices,Dictionary<string,int> dict)
        {
            var downloadConfig = new MqttDownloadConfig
            {
                MQTTConfigs = new List<MqttDownloadConfigItem>()
            };

            foreach (var device in devices)
            {
                var configItem = new MqttDownloadConfigItem
                {
                    MQTTName = device.Config.Name,
                    Vaild = device.Config.StartTls,
                    ServerType = GetServerType(device.Config.ServerType),
                    Server = device.Config.Address,
                    Port = int.TryParse(device.Config.Port, out int port) ? port : 1883,
                    User = device.Config.Username,
                    PW = device.Config.Password,
                    ClientID = device.Config.ClientId,
                    CleanSession = device.Config.ClearSession,
                    SSL = device.Config.SecurityLayer =="ssl",
                    KeepAlive = device.Config.Keepalive,
                    NetworkType = GetNetworkType(device.Config.CardType),
                    CAFile = device.Config.Cafile,
                    CertFile = device.Config.Certfile,
                    KeyFile = device.Config.Keyfile,
                    PubTopics = ConvertTopics(device.Config.PublishTopics,dict),
                    SubTopics = ConvertTopics(device.Config.SubscribeTopics,dict)
                };

                downloadConfig.MQTTConfigs.Add(configItem);
            }

            return downloadConfig;
        }

        /// <summary>
        /// 获取服务器类型，处理空值情况
        /// </summary>
        private static int GetServerType(string serverType)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(serverType))
                {
                    return DEFAULT_SERVER_TYPE;
                }
                var type = MqttUIConfig.GetServerTypeByName(serverType);
                return type?.Id ?? DEFAULT_SERVER_TYPE;
            }
            catch
            {
                return DEFAULT_SERVER_TYPE;
            }
        }

        /// <summary>
        /// 获取网络类型，处理空值情况
        /// </summary>
        private static int GetNetworkType(string cardType)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(cardType))
                {
                    return DEFAULT_NETWORK_TYPE;
                }
                var type = MqttUIConfig.GetNetworkCardByName(cardType);
                return type?.Id ?? DEFAULT_NETWORK_TYPE;
            }
            catch
            {
                return DEFAULT_NETWORK_TYPE;
            }
        }

        /// <summary>
        /// 获取主题类型，处理空值情况
        /// </summary>
        private static int GetTopicType(string topicType)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(topicType))
                {
                    return DEFAULT_TOPIC_TYPE;
                }
                var type = MqttUIConfig.GetTopicByName(topicType);
                return type?.Id ?? DEFAULT_TOPIC_TYPE;
            }
            catch
            {
                return DEFAULT_TOPIC_TYPE;
            }
        }

        /// <summary>
        /// 获取载荷类型，处理空值情况
        /// </summary>
        private static int GetPayloadType(string payloadFormat, Dictionary<string, int> dict)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(payloadFormat))
                {
                    return DEFAULT_PAYLOAD_TYPE;
                }
                var type = MqttUIConfig.GetPayloadByName(payloadFormat);
                // 判断type是否存在，不存在需要从dict获取
                if (type == null)
                {
                    if (dict.TryGetValue(payloadFormat, out int id))
                    {
                        return id;
                    }
                }
                return type?.Id ?? DEFAULT_PAYLOAD_TYPE;
            }
            catch
            {
                return DEFAULT_PAYLOAD_TYPE;
            }
        }

        /// <summary>
        /// 转换主题列表
        /// </summary>
        /// <param name="topics">原始主题列表</param>
        /// <returns>转换后的主题列表</returns>
        private static List<MqttDownloadTopic> ConvertTopics(List<DatabaseMqttTopic> topics,Dictionary<string,int> dict)
        {
            var downloadTopics = new List<MqttDownloadTopic>();

            foreach (var topic in topics)
            {
                var downloadTopic = new MqttDownloadTopic
                {
                    Topic = topic.Content,
                    QoS = GetQosLevel(topic.Qos),
                    Type = GetTopicType(topic.TopicType),
                    PayloadType = GetPayloadType(topic.PayloadFormat, dict),
                    UpIntervalS = topic.Interval,
                    Vaild = topic.Enabled
                };

                downloadTopics.Add(downloadTopic);
            }

            return downloadTopics;
        }

        /// <summary>
        /// 获取QoS级别
        /// </summary>
        /// <param name="qosString">QoS字符串</param>
        /// <returns>QoS级别</returns>
        private static int GetQosLevel(string qosString)
        {
            return qosString?.ToLower() switch
            {
                "qos0" => 0,
                "qos1" => 1,
                "qos2" => 2,
                _ => 0
            };
        }

        /// <summary>
        /// 将转换后的配置保存到文件
        /// </summary>
        /// <param name="downloadConfig">下载配置</param>
        /// <param name="filePath">文件路径</param>
        public static void SaveDownloadConfigToFile(MqttDownloadConfig downloadConfig, string filePath)
        {
            string jsonContent = JsonSerializer.Serialize(downloadConfig, JsonSerializerOptionsManager.Compact);
            File.WriteAllText(filePath, jsonContent);
        }
    }

    /// <summary>
    /// MQTT设备类
    /// </summary>
    public class DatabaseMqttDevice
    {
        [JsonPropertyName("id")]
        public int Id { get; set; }

        [JsonPropertyName("name")]
        public string Name { get; set; } = string.Empty;

        [JsonPropertyName("groupDeviceId")]
        public int GroupDeviceId { get; set; }

        [JsonPropertyName("config")]
        public DatabaseMqttConfig Config { get; set; } = new DatabaseMqttConfig();
    }

    /// <summary>
    /// MQTT配置类
    /// </summary>
    public class DatabaseMqttConfig
    {
        [JsonPropertyName("id")]
        public int Id { get; set; }

        [JsonPropertyName("name")]
        public string Name { get; set; } = string.Empty;

        [JsonPropertyName("address")]
        public string Address { get; set; } = string.Empty;

        [JsonPropertyName("port")]
        public string Port { get; set; } = string.Empty;

        [JsonPropertyName("clientId")]
        public string ClientId { get; set; } = string.Empty;

        [JsonPropertyName("username")]
        public string Username { get; set; } = string.Empty;

        [JsonPropertyName("password")]
        public string Password { get; set; } = string.Empty;

        [JsonPropertyName("keepalive")]
        public int Keepalive { get; set; }

        [JsonPropertyName("cardType")]
        public string CardType { get; set; } = string.Empty;

        [JsonPropertyName("serverType")]
        public string ServerType { get; set; } = string.Empty;

        [JsonPropertyName("publishTopics")]
        public List<DatabaseMqttTopic> PublishTopics { get; set; } = new List<DatabaseMqttTopic>();

        [JsonPropertyName("subscribeTopics")]
        public List<DatabaseMqttTopic> SubscribeTopics { get; set; } = new List<DatabaseMqttTopic>();

        [JsonPropertyName("securityLayer")]
        public string SecurityLayer { get; set; } = string.Empty;

        [JsonPropertyName("clearSession")]
        public bool ClearSession { get; set; }

        [JsonPropertyName("startTls")]
        public bool StartTls { get; set; }

        [JsonPropertyName("sslFileType")]
        public bool SslFileType { get; set; }

        [JsonPropertyName("cafile")]
        public string Cafile { get; set; } = string.Empty;

        [JsonPropertyName("certfile")]
        public string Certfile { get; set; } = string.Empty;

        [JsonPropertyName("keyfile")]
        public string Keyfile { get; set; } = string.Empty;
    }

    /// <summary>
    /// MQTT主题类
    /// </summary>
    public class DatabaseMqttTopic
    {
        [JsonPropertyName("id")]
        public int Id { get; set; }

        [JsonPropertyName("topic")]
        public string Topic { get; set; } = string.Empty;

        [JsonPropertyName("content")]
        public string Content { get; set; } = string.Empty;

        [JsonPropertyName("qos")]
        public string Qos { get; set; } = string.Empty;

        [JsonPropertyName("enabled")]
        public bool Enabled { get; set; }

        [JsonPropertyName("payloadFormat")]
        public string PayloadFormat { get; set; } = string.Empty;

        [JsonPropertyName("interval")]
        public int Interval { get; set; }

        [JsonPropertyName("topicType")]
        public string TopicType { get; set; } = string.Empty;
    }

    /// <summary>
    /// MQTT下载配置根类
    /// </summary>
    public class MqttDownloadConfig
    {
        [JsonPropertyName("MQTTConfigs")]
        public List<MqttDownloadConfigItem> MQTTConfigs { get; set; } = new List<MqttDownloadConfigItem>();
    }

    /// <summary>
    /// MQTT下载配置项类
    /// </summary>
    public class MqttDownloadConfigItem
    {
        [JsonPropertyName("MQTTName")]
        public string MQTTName { get; set; } = string.Empty;

        [JsonPropertyName("Vaild")]
        public bool Vaild { get; set; }

        [JsonPropertyName("ServerType")]
        public int ServerType { get; set; }

        [JsonPropertyName("Server")]
        public string Server { get; set; } = string.Empty;

        [JsonPropertyName("Port")]
        public int Port { get; set; }

        [JsonPropertyName("User")]
        public string User { get; set; } = string.Empty;

        [JsonPropertyName("PW")]
        public string PW { get; set; } = string.Empty;

        [JsonPropertyName("ClientID")]
        public string ClientID { get; set; } = string.Empty;

        [JsonPropertyName("CleanSession")]
        public bool CleanSession { get; set; }

        [JsonPropertyName("SSL")]
        public bool SSL { get; set; }

        [JsonPropertyName("KeepAlive")]
        public int KeepAlive { get; set; }

        [JsonPropertyName("PubTopics")]
        public List<MqttDownloadTopic> PubTopics { get; set; } = new List<MqttDownloadTopic>();

        [JsonPropertyName("SubTopics")]
        public List<MqttDownloadTopic> SubTopics { get; set; } = new List<MqttDownloadTopic>();

        [JsonPropertyName("CAFile")]
        public string CAFile { get; set; } = string.Empty;

        [JsonPropertyName("CertFile")]
        public string CertFile { get; set; } = string.Empty;

        [JsonPropertyName("KeyFile")]
        public string KeyFile { get; set; } = string.Empty;

        [JsonPropertyName("NetworkType")]
        public int NetworkType { get; set; }
    }

    /// <summary>
    /// MQTT下载主题类
    /// </summary>
    public class MqttDownloadTopic
    {
        [JsonPropertyName("Topic")]
        public string Topic { get; set; } = string.Empty;

        [JsonPropertyName("QoS")]
        public int QoS { get; set; }

        [JsonPropertyName("Type")]
        public int Type { get; set; }

        [JsonPropertyName("PayloadType")]
        public int PayloadType { get; set; }

        [JsonPropertyName("UpIntervalS")]
        public int UpIntervalS { get; set; }

        [JsonPropertyName("Vaild")]
        public bool Vaild { get; set; }
    }
}
